#include <iostream>
#include "matrix.h"
#include "dengebenjin.h"
using namespace std;

// 穷举，找出等额本息还款额
int deng_e_ben_xi(const int tmonth, const double total, const double monrate)
{
	//穷举的最后一个值，等额本息是一种越到后还款数额中本金部分越多的方式，所以第一个月还款不可能到本金/还款月
	const double lasttry = total/(double)tmonth;
	double ftry = lasttry;
	
	double monthsum;
	int moncount = 0;
	double tmptotal = total;
	double tmptotalbenjin = 0.0;
	double tmptotallixi = 0.0;
	while(ftry>0)
	{
		tmptotal = total;
		tmptotalbenjin = 0.0;
		tmptotallixi = 0.0;
		monthsum = ftry + total*monrate;
		moncount = 0;
		for(moncount = 0; moncount<tmonth; ++moncount)
		{
			double monthbenjin = monthsum - (tmptotal*monrate);

			tmptotal -= monthbenjin;

			tmptotalbenjin += monthbenjin;
			tmptotallixi += (tmptotal*monrate);
			
			//cout<<"ftry="<<ftry<<"\tmoncount="<<moncount<<"\ttmptotal="<<tmptotal<<"\ttotalbenjin="<<tmptotalbenjin<<"\ttotallixi="<<tmptotallixi<<endl;
			if(tmptotal<0.0)
			{
				break;
			}
		}
		//cout<<"monrate="<<monrate<<"\tftry="<<ftry<<"\tmonthsum="<<monthsum<<"\tmoncount="<<moncount<<"\ttmptotal="<<tmptotal<<"\ttotalbenjin="<<tmptotalbenjin<<"\ttotallixi="<<tmptotallixi<<endl;
		//if(tmptotal<0.0 && moncount==tmonth)
		if(tmptotal>0.0)
		{
			break;
		}
		ftry-=1.0;
	}
	cout<<"monrate="<<monrate<<"\tftry="<<ftry<<"\tmonthsum="<<monthsum<<"\tmoncount="<<moncount<<"\ttmptotal="<<tmptotal<<"\ttotalbenjin="<<tmptotalbenjin<<"\ttotallixi="<<tmptotallixi<<endl;
	return 0;
}

// 解线性方程组计算等额本息还款额
// tmonth 还款月数
// total 贷款本金总额
// monrate 贷款月利息
/*
	如果还款月是n，则可以列出如下的n+1元线性方程组

	benjin_m1 + total*monrate = benxi_month
	benjin_m2 + (total-benjin_m1)*monrate = benxi_month
	benjin_m3 + (total-benjin_m1-benjin_m2)*monrate = benxi_month
	......
	benjin_mn + (total-sum(benjin_m1,benjin_m[n-1]))*monrate = benxi_month
	sum(benjin_m1,benjin_mn) = total

	变换成标准n+1元线性方程组
	
	1.0*benjin_m1 			+ 0.0*benjin_m2 		+ 0.0*benjin_m3 +		...... + 0.0*benjin_mn + (-1.0)benxi_month = -(total*monrate)
	(-monrate)*benjin_m1 	+ (1.0)*benjin_m2 		+ 0.0*benjin_m3 +		...... + 0.0*benjin_mn + (-1.0)benxi_month = -(total*monrate)
	(-monrate)*benjin_m1 	+ (-monrate)*benjin_m2 	+ (1.0)*benjin_m3 + 	...... + 0.0*benjin_mn + (-1.0)benxi_month = -(total*monrate)
	......
	(-monrate)*benjin_m1 	+ (-monrate)*benjin_m2 	+ (-monrate)*benjin_m3 +...... + (1.0)*benjin_mn + (-1.0)benxi_month = -(total*monrate)
	1.0*benjin_m1           + 1.0*benjin_m2         + 1.0*benjin_m3 +		...... + (1.0)*benjin_mn + (0.0)benxi_month = total
*/
int deng_e_ben_xi_matrix(const int tmonth, const double total, const double monrate, unsigned int sumtopn)
{	
	double* mval = new double[(tmonth+1)*(tmonth+2)];
	int mvalindex = 0;
	// 构建前n行
	for(int row=0;row<tmonth;++row)
	{
		// 共有n+2列
		for(int field=0;field<(tmonth+2);++field)
		{
			if(field == tmonth)
			{
				// 如果是最后第二列 赋值 -1.0
				mval[mvalindex] = -1.0;
			}
			else if(field == (tmonth+1))
			{
				// 如果是最后第一列 赋值 -1.0
				mval[mvalindex] = -(total*monrate);
			}
			else if(field < row)
			{
				// 如果是对角线左边的 赋值 -monrate
				mval[mvalindex] = -monrate;
			}
			else if(field == row)
			{
				// 如果是对角线上的 赋值 1.0
				 mval[mvalindex] = 1.0;
			}
			else
			{
				// 如果是对角线右边的 赋值 0.0
				mval[mvalindex] = 0.0;
			}
			++mvalindex;
		}
	}

	// 构建第n+1行
	for(int loop=0;loop<(tmonth);++loop)
	{
		// 第n+1行前n个元素都是1.0
		mval[mvalindex] = 1.0;
		++mvalindex;
	}
	// 第n+1行第n+1个元素是 0.0
	mval[mvalindex] = 0.0;
	++mvalindex;
	// 第n+1行第n+2个元素是 0.0
	mval[mvalindex] = total;

	jieningMatrix xisusm((tmonth+2), (tmonth+1), mval);

	xisusm.doPrint();
	
	/*
	jieningSquareMatrix tmpsm = xisusm.getSubMatrix(tmonth, -1);
	tmpsm.doPrint();
	double detval = tmpsm.doDetComput();
	cout<<" detval ="<<detval<<endl;
	return 0;
	//*/

	/*
	cout<<endl<<endl<<"output matrix"<<endl;
	for(int rr=0;rr<(tmonth+1);++rr)
	{
		cout<<"|";
		for(int ll=0;ll<(tmonth+2);++ll)
		{
			cout<<xisusm.getValue(ll, rr)<<"\t";
		}
		cout<<"|"<<endl;
	}
	return 0;
	//*/

	jieningMatrix rem = xisusm.computeFCZ();
	rem.doPrint();

	cout<<"sum top n"<<endl;
	double sumtomnval = 0.0;
	if(sumtopn > 1)
	{
		for(unsigned int j=0;j<sumtopn;++j)
		{
			sumtomnval += rem.getValue(rem.getXlen()-1, j);
			cout<<"  month "<<j<<" : "<<rem.getValue(rem.getXlen()-1, j)<<", sum : "<<sumtomnval<<endl;
		}
	}

	double em00 = rem.getValue(rem.getXlen()-1,0);
	double emnn = rem.getValue(rem.getXlen()-1, rem.getYlen()-1);
	cout<<endl;
	cout<<"total:	"<<total<<endl;
	cout<<"tmonth:	"<<tmonth<<endl;
	cout<<"monrate:	"<<monrate<<endl;
	cout<<"benjin month1:"<<em00<<endl;
	cout<<"lixi month1:"<<(emnn-em00)<<endl;
	cout<<"benxi month:"<<emnn<<endl;
	if(sumtopn > 1)
	{
		cout<<"sum top "<<sumtopn<<": "<<sumtomnval<<endl;
	}
	return 0;
}
